from fuzzywuzzy import fuzz
import re
from collections import Counter

def correct(string):
    # 定义一个函数，用于将文本中的单词提取出来
    def words(text):
        return re.findall(r'\S+', text)
    with open('corpus.txt', 'r', encoding="utf-8") as corpus_file:
        corpus = words(corpus_file.read())
    
    # 定义一个函数，用于将单词和其出现频率组成元组
    word_counter = Counter(corpus)
    word = string
    matches = []
    # 如果单词是语料库中单词的子串,则减去两者相差的单词长度（如果完全相同，则表示在忽略大小写的情况下相似度为100%）
    for candidate in word_counter.items():
        if word.lower() in candidate[0].lower():
            if word.lower() == candidate[0].lower():
                if word == candidate[0]:
                    similarity = 120
                else:
                    similarity = 110
            else:
                similarity = 100 - (len(candidate[0].lower())-len(word.lower()))
        # 如果单词不是语料库中单词的子串,则使用Levenshtein距离计算相似度值
        else:
            similarity = fuzz.ratio(word.lower(), candidate[0].lower())
        matches.append([candidate[0], similarity, candidate[1]])
    # 按照相似度降序排列
    sorted_matches = sorted(matches, key=lambda x: x[1], reverse=True)

    for match in sorted_matches[:20]:  # 输出前20个相似度最高的匹配项
        print(f"Match: {match[0]}, Similarity: {match[1]}, Frequency: {match[2]}")


    sorted_matches = sorted_matches[:20]
    min_val = min(sorted_matches, key=lambda x: x[2])  # 找到第3维度的值最小的元素
    max_val = max(sorted_matches, key=lambda x: x[2])  # 找到第3维度的值最大的元素

    # 将出现频率归一化，使频率值在0~5之间，并与相似度值加权计算，并按照加权和降序排列
    sorted_matches = sorted(sorted_matches, key=lambda x: x[1]+(x[2]-min_val[2])*5/(max_val[2]-min_val[2]), reverse=True)

    print(f"Misspelled word: {word}")
    for match in sorted_matches[:20]:  # 输出前20个相似度最高的匹配项
        print(f"Match: {match[0]}, Similarity: {match[1]}, Frequency: {match[2]}")

    best_match = sorted_matches[0][0]  # 获取相似度最高的匹配项

    print(f"Corrected word: {best_match}")
    return best_match


misspelled_word = 'LinEx'
corrected_word = correct(misspelled_word)